package com.css.fxfzdzzh.modules.reportManagement.service;

import com.css.fxfzdzzh.base.response.RestResponse;
import com.css.fxfzdzzh.modules.mapManagement.repository.MapRepository;
import com.css.fxfzdzzh.modules.mapManagement.vo.MapAttachment;
import com.css.fxfzdzzh.modules.reportManagement.entity.BreakReport;
import com.css.fxfzdzzh.modules.reportManagement.entity.HistoryReport;
import com.css.fxfzdzzh.modules.reportManagement.entity.ReportBack;
import com.css.fxfzdzzh.modules.reportManagement.param.PageQueryParam;
import com.css.fxfzdzzh.modules.reportManagement.repository.ReportRepository;
import com.css.fxfzdzzh.modules.surfaceRupture.entity.SurfaceRupture;
import com.css.fxfzdzzh.modules.surfaceRupture.repository.SurfaceRuptureRepository;
import com.css.fxfzdzzh.util.*;
import com.css.fxfzdzzh.web.PlatformSessionContext;
import com.css.fxfzdzzh.zcpt.sys.entity.SUser;
import com.css.fxfzdzzh.zcpt.sys.service.SUserService;
import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.config.Configure;
import com.deepoove.poi.data.PictureRenderData;
import com.deepoove.poi.plugin.table.HackLoopTableRenderPolicy;
import com.deepoove.poi.xwpf.NiceXWPFDocument;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ResourceUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author Dbj
 * @date 2023年05月09日  15:19
 */
@Service
public class ReportService {

    @Value("${file.localDir}")
    private String localDir;
    @Resource
    ReportRepository reportRepository;

    @Resource
    SurfaceRuptureRepository surfaceRuptureRepository;

    @Resource
    SUserService sUserService;

    @Resource
    MapRepository mapRepository;

    public Map<String, Object> breakReportPage(PageQueryParam param, int curPage, int pageSize) {
        return reportRepository.breakReportPage(param,curPage,pageSize);
    }

    @Transactional(rollbackFor = Exception.class)
    public BreakReport createBreakReport(String num) throws Exception {
        BreakReport report = new BreakReport();
        List<SurfaceRupture> surfaceRuptureList = surfaceRuptureRepository.getByNum(num);
        //获取所有的地表破裂带的图片
        List<MapAttachment> mapAttachmentList = mapRepository.getMapAttachmentByCategory(Arrays.asList("8","9"));
        Map<String, Object> paramMap = new HashMap<>();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月");
        paramMap.put("createTime",sdf.format(new Date()));
        buildImage(mapAttachmentList,paramMap);
        Map<String, String> map = createReport(paramMap);
        if(PlatformObjectUtils.isNotEmpty(surfaceRuptureList) && surfaceRuptureList.size()>0){
            SurfaceRupture surfaceRupture = surfaceRuptureList.get(0);
            String reportId = "";
            if(StringUtils.isBlank(surfaceRupture.getReportId())){
                System.out.println("开始组建数据了1");
                reportId = UUIDGenerator.getUUID();
                //表示之前未生成过报告信息
                BreakReport breakReport = new BreakReport();
                breakReport.setDtbrId(reportId);
                breakReport.setReportSavePath(map.get("rootPath"));
                breakReport.setCheckStatus("0");
                breakReport.setNum(surfaceRupture.getNum());
                breakReport.setDistrict(surfaceRupture.getProvince()+surfaceRupture.getCity()+surfaceRupture.getCounty());
                setData(breakReport,map);
                //save
                reportRepository.save(breakReport);
                //关联地表劈裂带
                List<String> idList = surfaceRuptureList.stream().map(SurfaceRupture::getDsrId).collect(Collectors.toList());
                surfaceRuptureRepository.updateReportId(idList,reportId);
            }else{
                System.out.println("开始组建数据了2");
                BreakReport breakReport = reportRepository.getReportById(surfaceRupture.getReportId());
                reportId = breakReport.getDtbrId();
                setData(breakReport,map);
                //update
                reportRepository.updateSystemCreateReport(breakReport);
            }
            System.out.println("组建数据完成");
            return reportRepository.getReportById(reportId);
        }
        System.out.println("没有任何返回数据");
        return new BreakReport();
    }

    private void buildImage(List<MapAttachment> mapAttachmentList, Map<String, Object> paramMap) {
        if(PlatformObjectUtils.isNotEmpty(mapAttachmentList)&& mapAttachmentList.size()>0){
            Map<String, List<MapAttachment>> collect = mapAttachmentList.stream().collect(Collectors.groupingBy(MapAttachment::getMapLevel2Category));
            //行政区概况
            Optional.ofNullable(collect.get("18")).ifPresent(x->{
                if(PlatformObjectUtils.isNotEmpty(x)){
                    paramMap.put("districtPic",new PictureRenderData(1000, 600, x.get(0).getAttachFullPath().replace("_","\\")));
                }
            });
            //地形地貌概况
            Optional.ofNullable(collect.get("21")).ifPresent(x->{
                if(PlatformObjectUtils.isNotEmpty(x)){
                    paramMap.put("landformPic",new PictureRenderData(1000, 600, x.get(0).getAttachFullPath().replace("_","\\")));
                }
            });
            //卫星影像概况
            Optional.ofNullable(collect.get("19")).ifPresent(x->{
                if(PlatformObjectUtils.isNotEmpty(x)){
                    paramMap.put("satelliteImage",new PictureRenderData(1000, 600, x.get(0).getAttachFullPath().replace("_","\\")));
                }
            });
           //地震地质构造情况
            Optional.ofNullable(collect.get("20")).ifPresent(x->{
                if(PlatformObjectUtils.isNotEmpty(x)){
                    paramMap.put("earquakeConstructPic",new PictureRenderData(1000, 600, x.get(0).getAttachFullPath().replace("_","\\")));
                }
            });

           //发震构造评估
            Optional.ofNullable(collect.get("22")).ifPresent(x->{
                if(PlatformObjectUtils.isNotEmpty(x)){
                    paramMap.put("seismogenicConstructPic",new PictureRenderData(1000, 600, x.get(0).getAttachFullPath().replace("_","\\")));
                }
            });

            //发震构造评估
            Optional.ofNullable(collect.get("23")).ifPresent(x->{
                if(PlatformObjectUtils.isNotEmpty(x)){
                    paramMap.put("breakPic",new PictureRenderData(1000, 600, x.get(0).getAttachFullPath().replace("_","\\")));
                }
            });
        }

    }

    //为系统生成的数据设置基础数据
    private void setData(BreakReport breakReport,Map<String, String> map){
        breakReport.setSystemCreateBreakReportName("地表破裂带报告.docx");
        breakReport.setDiskSystemCreateBreakReportName(map.get("docxName"));
        breakReport.setSystemBreakCreateTime(new Date());
        breakReport.setSystemBreakCreateUserId(PlatformSessionContext.getUserID());
    }

    private  Map<String, String> createReport(Map<String, Object> paramMap) throws Exception {
        // 文件存放根目录
        String rootPath = localDir;
        File dir = new File(rootPath);
        // 文件夹不存在则创建
        if (!dir.exists()) {
            boolean mkdir = dir.mkdir();
        }
        Date now = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        String nowStr = sdf.format(now);
        String desFileName = "地表破裂带报告" +nowStr+ ".docx";
        String docxPath =  rootPath +File.separator+ desFileName;
        File file =  ResourceUtils.getFile("classpath:template/地表破裂带报告.docx");
        System.out.println("模板路径:--"+file.getAbsolutePath());
        if(!file.exists()){
            throw new RuntimeException("报告生成失败，获取不到模板信息！");
        }
        InputStream inputStream = new FileInputStream(file);

        //渲染表格  动态行
        HackLoopTableRenderPolicy policy = new HackLoopTableRenderPolicy();
        Configure config = Configure.newBuilder().build();
        XWPFTemplate template = XWPFTemplate.compile(inputStream,config).render(paramMap);
        OutputStream outDocx = Files.newOutputStream(Paths.get(docxPath));
        NiceXWPFDocument xwpfDocument = template.getXWPFDocument();
        // 输出word
        template.getXWPFDocument().write(outDocx);
        outDocx.flush();
        outDocx.close();
        inputStream.close();
        Map<String, String> map = new HashMap<>(4);
        map.put("rootPath", rootPath);
        map.put("docxName", desFileName);
        System.out.println("模板数据生成完成");
        return map;
    }

    public BreakReport getReport(String reportId) {
        return reportRepository.getReportById(reportId);
    }

    public void downloadReport(String reportId, String type, HttpServletResponse res) {
        BreakReport report = reportRepository.getReportById(reportId);
        String filePath = report.getReportSavePath();
        String fileName = "";
        if ("1".equals(type)) {
            //系统生成的报告
            fileName = report.getDiskSystemCreateBreakReportName();
        } else if ("2".equals(type)){
            //用户上传的报告
            fileName = report.getDiskUploadBreakReportName();
        } else if ("3".equals(type)){
            //审核不通过退回的附件
            fileName = report.getRejectFile();
        }

        FileUploadUtil.download(filePath + File.separator + fileName, res);
    }

    @Transactional(rollbackFor = Exception.class)
    public RestResponse uploadReport(MultipartFile file, String num) throws IOException {
        if (file == null) {
            return ResponseCreator.createFailResponse("上传失败，请选择文件");
        }
        List<SurfaceRupture> surfaceRuptureList = surfaceRuptureRepository.getByNum(num);
        SurfaceRupture surfaceRupture = new SurfaceRupture();
        if(PlatformObjectUtils.isNotEmpty(surfaceRuptureList)){
            surfaceRupture = surfaceRuptureList.get(0);
        }
        String reportId = surfaceRupture.getReportId();
        //获取文件名称
        String fileName = file.getOriginalFilename();
        assert fileName != null;
        String filePrefix = fileName.split("\\.")[0];
        String fileType = fileName.split("\\.")[1];
        Date now = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        String nowStr = sdf.format(now);
        String localReportName = filePrefix + nowStr + "." + fileType;
        //获取文件上传的本地路径
        String savePath = localDir;
        //上传文件
        uploadFile(localReportName, savePath, file);
        if(StringUtils.isBlank(reportId)){
            //表示还未生成过报告信息
            BreakReport report = new BreakReport();
            reportId = UUIDGenerator.getUUID();
            report.setDtbrId(reportId);
            report.setUploadBreakReportName(fileName);
            report.setDiskUploadBreakReportName(localReportName);
            report.setUploadBreakReportTime(new Date());
            report.setUploadBreakUserId(PlatformSessionContext.getUserID());
            report.setReportSavePath(savePath);
            report.setCheckStatus("0");
            report.setNum(surfaceRupture.getNum());
            report.setDistrict(surfaceRupture.getProvince()+surfaceRupture.getCity()+surfaceRupture.getCounty());
            reportRepository.save(report);
            //关联地表劈裂带
            List<String> idList = surfaceRuptureList.stream().map(SurfaceRupture::getDsrId).collect(Collectors.toList());
            surfaceRuptureRepository.updateReportId(idList,reportId);
        }else{
            //已经存在报告信息
            BreakReport report = reportRepository.getReportById(reportId);
            report.setUploadBreakReportName(fileName);
            report.setDiskUploadBreakReportName(localReportName);
            report.setUploadBreakReportTime(new Date());
            report.setUploadBreakUserId(PlatformSessionContext.getUserID());
            reportRepository.updateUploadReport(report);
        }
        //保存历史上传报告
        saveHistoryReport(fileName,localReportName,localDir,surfaceRupture.getNum());
        return ResponseCreator.createSuccessResponse(reportRepository.getReportById(reportId));
    }

    private void saveHistoryReport(String fileName, String localReportName, String localDir,String num) {
        HistoryReport historyReport = new HistoryReport();
        historyReport.setDthrId(UUIDGenerator.getUUID());
        historyReport.setReportName(fileName);
        historyReport.setDiskReportName(localReportName);
        historyReport.setFileSavePath(localDir);
        String userID ="80cd530287e54c6788925adf2dfc9da1";
        historyReport.setUploadUserId(userID);
        String userJson = sUserService.getSUser(userID);
        SUser sUser = CreateGson.createGson().fromJson(userJson, SUser.class);
        historyReport.setUploadUserName(sUser.getUserName());
        historyReport.setUploadTime(new Date());
        historyReport.setReportType("1");
        historyReport.setNum(num);
        reportRepository.saveHistoryReport(historyReport);
    }

    private void uploadFile(String fileName, String savePath, MultipartFile multipartFile) throws IOException {
        // 获取文件的后缀名
        assert fileName != null;
        //判断文件夹是否存在如果不存在则创建
        if (!new File(savePath).exists()) {
            new File(savePath).mkdirs();
        }
        File file = new File(savePath, fileName);
        multipartFile.transferTo(file);
    }

    public Map<String, Object> getHistoryReport(String num,String reportType, int curPage, int pageSize) {
        return reportRepository.getHistoryReportByTaskId(num, reportType,curPage, pageSize);
    }

    public void downloadHistoryReport(String dthrId, HttpServletResponse res) throws Exception{
        HistoryReport report = reportRepository.getHistoryReportById(dthrId);
        if(report==null){
            throw new RuntimeException("查询不到要下载的文件");
        }
        String filePath = report.getFileSavePath();
        String fileName = report.getDiskReportName();
        FileUploadUtil.download(filePath + File.separator + fileName, res);
    }

    public void submitCheak(String reportId) throws Exception{
        String userID =PlatformSessionContext.getUserID();
        String userJson = sUserService.getSUser(userID);
        SUser sUser = CreateGson.createGson().fromJson(userJson, SUser.class);
        BreakReport reportById = reportRepository.getReportById(reportId);
        if(StringUtils.isBlank(reportById.getUploadBreakReportName())){
            throw new RuntimeException("提交审核失败,上传最终版本报告后才可提交审核");
        }
        reportRepository.submitCheak(reportId,userID,sUser.getUserName());
    }

    public ReportBack getBackReport(String reportId) {
        BreakReport report = reportRepository.getReportById(reportId);
        if(PlatformObjectUtils.isNotEmpty(report) && "2".equals(report.getCheckStatus())){
            ReportBack reportBack = new ReportBack();
            reportBack.setCheckStatus("不通过");
            reportBack.setRejectAdvice(report.getRejectAdvice());
            reportBack.setRejectFile(report.getRejectFile());
            reportBack.setRejectRealFile(report.getRejectRealFile());
            reportBack.setReportSavePath(report.getReportSavePath());
            reportBack.setAuditTime(report.getAuditTime());
            reportBack.setAuditUserName(report.getAuditUserName());
            reportBack.setReportId(reportId);
            return reportBack;
        }
        return new ReportBack();
    }
}
